{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Tce3stUlHN0L"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "tuOe1ymfHZPu"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qFdPvlXBOdUN"
      },
      "source": [
        "# Keras Tuner 소개"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MfBg1C5NB3X0"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td><a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/keras/keras_tuner\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\">TensorFlow.org에서 보기</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/en/tutorials/keras/keras_tuner.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\">Google Colab에서 실행하기</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/en/tutorials/keras/keras_tuner.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\">GitHub에서소스 보기</a></td>\n",
        "  <td><a href=\"https://storage.googleapis.com/tensorflow_docs/docs/site/en/tutorials/keras/keras_tuner.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\">노트북 다운로드하기</a></td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xHxb-dlhMIzW"
      },
      "source": [
        "## 개요\n",
        "\n",
        "Keras Tuner는 TensorFlow 프로그램에 대한 최적의 하이퍼파라미터 세트를 선택하는 데 도움을 주는 라이브러리입니다. 머신러닝(ML) 애플리케이션에 대한 올바른 하이퍼파라미터 세트를 선택하는 과정을 *하이퍼파라미터 조정* 또는 *하이퍼튜닝*이라고 합니다.\n",
        "\n",
        "하이퍼파라미터는 훈련 프로세스 및 ML 모델의 토폴로지를 제어하는 변수입니다. 이러한 변수는 훈련 과정에서 일정하게 유지되며 ML 프로그램의 성능에 직접적으로 영향을 미칩니다. 하이퍼파라미터에는 두 가지 유형이 있습니다.\n",
        "\n",
        "1. 숨겨진 레이어의 수 및 너비와 같이 모델 선택에 영향을 미치는 **모델 하이퍼파라미터**\n",
        "2. SGD(Stochastic Gradient Descent)의 학습률 및 KNN(k Nearest Neighbors) 분류자의 최근접 이웃 수와 같은 학습 알고리즘의 속도와 품질에 영향을 주는 **알고리즘 하이퍼파라미터**\n",
        "\n",
        "이 튜토리얼에서는 Keras Tuner를 사용하여 이미지 분류 애플리케이션에 하이퍼튜닝을 수행합니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MUXex9ctTuDB"
      },
      "source": [
        "## 설정"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "IqR2PQG4ZaZ0"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "from tensorflow import keras\n",
        "\n",
        "import IPython"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "g83Lwsy-Aq2_"
      },
      "source": [
        "Keras Tuner를 설치하고 가져옵니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "_leAIdFKAxAD"
      },
      "outputs": [],
      "source": [
        "!pip install -U keras-tuner\n",
        "import kerastuner as kt"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ReV_UXOgCZvx"
      },
      "source": [
        "## 데이터세트 다운로드 및 준비하기\n",
        "\n",
        "이 튜토리얼에서는 Keras Tuner를 사용하여 [Fashion MNIST 데이터세트](https://github.com/zalandoresearch/fashion-mnist)에서 의류 이미지를 분류하는 머신러닝 모델에 가장 적합한 하이퍼파라미터를 찾습니다. "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HljH_ENLEdHa"
      },
      "source": [
        "데이터를 로드합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "OHlHs9Wj_PUM"
      },
      "outputs": [],
      "source": [
        "(img_train, label_train), (img_test, label_test) = keras.datasets.fashion_mnist.load_data()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "bLVhXs3xrUD0"
      },
      "outputs": [],
      "source": [
        "# Normalize pixel values between 0 and 1\n",
        "img_train = img_train.astype('float32') / 255.0\n",
        "img_test = img_test.astype('float32') / 255.0"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "K5YEL2H2Ax3e"
      },
      "source": [
        "## 모델 정의하기\n",
        "\n",
        "하이퍼튜닝을 위한 모델을 빌드할 때는 모델 아키텍처와 더불어 하이퍼파라미터 검색 공간도 정의합니다. 하이퍼튜닝을 위해 설정하는 모델을 *하이퍼 모델*이라고 합니다.\n",
        "\n",
        "두 가지 접근 방식을 통해 하이퍼 모델을 정의할 수 있습니다.\n",
        "\n",
        "- 모델 빌더 함수 사용\n",
        "- Keras Tuner API의 `HyperModel` 클래스를 하위 클래스화\n",
        "\n",
        "또한 두 개의 사전 정의된 `HyperModel` - 클래스인 [HyperXception](https://keras-team.github.io/keras-tuner/documentation/hypermodels/#hyperxception-class)과 [HyperResNet](https://keras-team.github.io/keras-tuner/documentation/hypermodels/#hyperresnet-class)을 컴퓨터 비전 애플리케이션에 사용할 수 있습니다.\n",
        "\n",
        "이 튜토리얼에서는 모델 빌더 함수를 사용하여 이미지 분류 모델을 정의합니다. 모델 빌더 함수는 컴파일된 모델을 반환하고 인라인으로 정의한 하이퍼파라미터를 사용하여 모델을 하이퍼튜닝합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZQKodC-jtsva"
      },
      "outputs": [],
      "source": [
        "def model_builder(hp):\n",
        "  model = keras.Sequential()\n",
        "  model.add(keras.layers.Flatten(input_shape=(28, 28)))\n",
        "  \n",
        "  # Tune the number of units in the first Dense layer\n",
        "  # Choose an optimal value between 32-512\n",
        "  hp_units = hp.Int('units', min_value = 32, max_value = 512, step = 32)\n",
        "  model.add(keras.layers.Dense(units = hp_units, activation = 'relu'))\n",
        "  model.add(keras.layers.Dense(10))\n",
        "\n",
        "  # Tune the learning rate for the optimizer \n",
        "  # Choose an optimal value from 0.01, 0.001, or 0.0001\n",
        "  hp_learning_rate = hp.Choice('learning_rate', values = [1e-2, 1e-3, 1e-4]) \n",
        "  \n",
        "  model.compile(optimizer = keras.optimizers.Adam(learning_rate = hp_learning_rate),\n",
        "                loss = keras.losses.SparseCategoricalCrossentropy(from_logits = True), \n",
        "                metrics = ['accuracy'])\n",
        "  \n",
        "  return model"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0J1VYw4q3x0b"
      },
      "source": [
        "## 튜너를 인스턴스화하고 하이퍼튜닝 수행하기\n",
        "\n",
        "튜너를 인스턴스화하여 하이퍼튜닝을 수행합니다. Keras Tuner에는 `RandomSearch`, `Hyperband`, `BayesianOptimization` 및 `Sklearn`의 네 가지 튜너가 있습니다. 이 튜토리얼에서는 [Hyperband](https://arxiv.org/pdf/1603.06560.pdf) 튜너를 사용합니다.\n",
        "\n",
        "Hyperband 튜너를 인스턴스화하려면 최적화할 하이퍼모델인 `objective`, 및 훈련할 최대 epoch 수(`max_epochs`)를 지정해야 합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "oichQFly6Y46"
      },
      "outputs": [],
      "source": [
        "tuner = kt.Hyperband(model_builder,\n",
        "                     objective = 'val_accuracy', \n",
        "                     max_epochs = 10,\n",
        "                     factor = 3,\n",
        "                     directory = 'my_dir',\n",
        "                     project_name = 'intro_to_kt') "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VaIhhdKf9VtI"
      },
      "source": [
        "Hyperband 튜닝 알고리즘은 적응형 리소스 할당 및 조기 중단을 사용하여 고성능 모델에서 신속하게 수렴합니다. 이것은 스포츠 챔피언십 스타일 브래킷을 사용하여 수행됩니다. 이 알고리즘은 몇 개의 epoch에 대해 많은 수의 모델을 훈련하고 최고 성능을 보이는 절반만 다음 단계로 넘깁니다. Hyperband는 1 + log<sub><code>factor</code></sub>( `max_epochs`)를 계산하고 이를 가장 가까운 정수로 반올림하여 한 브래킷에서 훈련할 모델 수를 결정합니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "oTeamrUWOJRb"
      },
      "source": [
        "하이퍼파라미터 검색을 실행하기 전에 훈련 단계가 끝날 때마다 훈련 결과를 지우도록 콜백을 정의합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Bbr_8QE76PJd"
      },
      "outputs": [],
      "source": [
        "class ClearTrainingOutput(tf.keras.callbacks.Callback):\n",
        "  def on_train_end(*args, **kwargs):\n",
        "    IPython.display.clear_output(wait = True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "UKghEo15Tduy"
      },
      "source": [
        "하이퍼파라미터 검색을 실행합니다. 검색 메서드의 인수는 위의 콜백 외에 `tf.keras.model.fit`에 사용되는 인수와 같습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "dSBQcTHF9cKt"
      },
      "outputs": [],
      "source": [
        "tuner.search(img_train, label_train, epochs = 10, validation_data = (img_test, label_test), callbacks = [ClearTrainingOutput()])\n",
        "\n",
        "# Get the optimal hyperparameters\n",
        "best_hps = tuner.get_best_hyperparameters(num_trials = 1)[0]\n",
        "\n",
        "print(f\"\"\"\n",
        "The hyperparameter search is complete. The optimal number of units in the first densely-connected\n",
        "layer is {best_hps.get('units')} and the optimal learning rate for the optimizer\n",
        "is {best_hps.get('learning_rate')}.\n",
        "\"\"\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Lak_ylf88xBv"
      },
      "source": [
        "이 튜토리얼을 마치려면 검색에서 최적의 하이퍼파라미터로 모델을 재훈련합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "McO82AXOuxXh"
      },
      "outputs": [],
      "source": [
        "# Build the model with the optimal hyperparameters and train it on the data\n",
        "model = tuner.hypermodel.build(best_hps)\n",
        "model.fit(img_train, label_train, epochs = 10, validation_data = (img_test, label_test))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "EQRpPHZsz-eC"
      },
      "source": [
        "`my_dir/intro_to_kt` 디렉토리에는 하이퍼파라미터 검색 중에 실행되는 모든 시험(모델 구성)에 대한 상세 로그와 체크포인트가 들어 있습니다. 하이퍼파라미터 검색을 다시 실행하면 Keras Tuner가 이러한 로그의 기존 상태를 사용하여 검색을 재개합니다. 이 동작을 비활성화하려면 튜너를 인스턴스화하는 동안 추가 `overwrite = True` 인수를 전달합니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sKwLOzKpFGAj"
      },
      "source": [
        "## 요약\n",
        "\n",
        "이 튜토리얼에서는 Keras Tuner를 사용하여 모델의 하이퍼파라미터를 조정하는 방법을 배웠습니다. Keras Tuner에 대한 자세한 내용은 다음 추가 자료를 확인하세요.\n",
        "\n",
        "- [TensorFlow 블로그의 Keras Tuner](https://blog.tensorflow.org/2020/01/hyperparameter-tuning-with-keras-tuner.html)\n",
        "- [Keras Tuner 웹 사이트](https://keras-team.github.io/keras-tuner/)\n",
        "\n",
        "모델 하이퍼파라미터를 능동적으로 조정하기 위한 TensorBoard의 [HParams Dashboard](https://www.tensorflow.org/tensorboard/hyperparameter_tuning_with_hparams)도 확인해 보세요."
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [
        "Tce3stUlHN0L"
      ],
      "name": "keras_tuner.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
